home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / nshellmegasource1.50 / mega src / commands / match.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-27  |  9.3 KB  |  401 lines  |  [TEXT/KAHL]

  1. /* ========== the commmand file: ==========
  2.  
  3.     match.c
  4.     
  5.     Copyright (c) 1994 Newport Software Development
  6.     
  7.     You may distribute unmodified copies of this file for
  8.     noncommercial purposes.  You may use this file as a
  9.     reference when writing your own nShell(tm) commands.
  10.     
  11.     All other rights are reserved.
  12.     
  13.    ========== the commmand file: ========== */
  14.  
  15. #define    MATCH_BUF_SIZE    2048
  16.  
  17. #ifdef __MWERKS__            // CodeWarrior requires an A4 setup
  18. #include <A4Stuff.h>
  19. #endif
  20.  
  21. #include <script.h>
  22. #include <string.h>
  23.  
  24. #include "nshc.h"
  25.  
  26. #include "arg_utl.proto.h"
  27. #include "fss_utl.proto.h"
  28. #include "fss_utl2.proto.h"
  29. #include "nshc_utl.proto.h"
  30. #include "str_utl.proto.h"
  31.  
  32. // data definition - this struct is the root of all data
  33.  
  34. typedef struct {
  35.  
  36.     int        by_file;        // 1 if files are listed, 0 if stdin
  37.     int        got_fss;        // 1 if FSSpec calls are available
  38.     int        arg;            // next file to process in arg list
  39.     int        found;            // 1 if the pattern was found at least once
  40.     short    p_arg;            // position of '-p' in arg list
  41.     short    fref;            // file ref. number, 0 if no file open
  42.     Str255    pattern;        // the pattern for which we search
  43.     Str255    line;            // the line we are currently looking at
  44.     int        line_pos;        // the place to put the next char in 'line'
  45.  
  46. } t_match_data;
  47.  
  48. typedef    t_match_data    **t_match_hndl;
  49.  
  50. /* ======================================== */
  51.  
  52. // prototypes - utility
  53.  
  54. void match_bad( t_nshc_parms *nshc_parms, int code );
  55. void match_bad_file( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, StringPtr msg );
  56. void match_good( t_nshc_parms *nshc_parms, t_match_hndl mData );
  57.  
  58. // prototypes - file copy routines
  59.  
  60. void match_open( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_hndl mData );
  61. void match_read_write( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_hndl mData );
  62.  
  63. // prototypes - console copy routines
  64.  
  65. void match_console( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_hndl mData );
  66.  
  67. // prototypes - state machine
  68.  
  69. void match_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls  );
  70. void match_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  71. void match_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls );
  72.  
  73. /* ======================================== */
  74.  
  75. // utility routines
  76.  
  77. /* ======================================== */
  78.  
  79. void match_bad(  t_nshc_parms *nshc_parms, int code )
  80. {
  81.     nshc_parms->action = nsh_stop;
  82.     nshc_parms->result = code;
  83. }
  84.  
  85. void match_bad_file(  t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, StringPtr msg )
  86. {
  87.     nshc_calls->NSH_putStr_err("\pmatch: File access error (");
  88.     nshc_calls->NSH_putStr_err(msg);
  89.     nshc_calls->NSH_putStr_err("\p)\r");
  90.  
  91.     nshc_parms->action = nsh_stop;
  92.     nshc_parms->result = NSHC_ERR_GENERAL;
  93. }
  94.  
  95. void match_good( t_nshc_parms *nshc_parms, t_match_hndl mData )
  96. {
  97.     nshc_parms->action = nsh_stop;
  98.     
  99.     if ( (**mData).found )
  100.         nshc_parms->result = 0;
  101.     else
  102.         nshc_parms->result = 1;
  103. }
  104.  
  105. /* ======================================== */
  106.  
  107. // file access routines
  108.  
  109. /* ======================================== */
  110.  
  111. void match_open( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_hndl mData )
  112. {
  113.     int        result;
  114.     long    dirID;
  115.     Boolean    isDir;
  116.     FSSpec    fss;
  117.     
  118.     (**mData).fref = 0;
  119.     (**mData).line_pos = 0;
  120.  
  121.     // =====> skip the -p option
  122.     
  123.     if ( (**mData).arg == (**mData).p_arg )
  124.         (**mData).arg += 2;
  125.         
  126.     if ( (**mData).arg >= nshc_parms->argc ) {
  127.         match_good( nshc_parms, mData );
  128.         return;
  129.         }
  130.     
  131.     // =====> convert path to fsspec
  132.     
  133.     result = arg_to_fss( nshc_parms, nshc_calls, (**mData).arg, &fss );
  134.  
  135.     (**mData).arg++;
  136.     
  137.     if (result) {
  138.         match_bad( nshc_parms, result );
  139.         return;
  140.         }
  141.     
  142.     result = fss_to_DirID( &fss, &dirID, &isDir );
  143.         
  144.     if (( result == noErr) && isDir)
  145.         return;
  146.             
  147.     if ( result == fnfErr ) {
  148.         nshc_calls->NSH_putStr_err("\pmatch: File not found = ");
  149.         nshc_calls->NSH_putStr_err((StringPtr)fss.name);
  150.         nshc_calls->NSH_putchar('\r');
  151.         return;
  152.         }
  153.             
  154.     if (!result)
  155.         result = fss_OpenDF((**mData).got_fss, &fss, fsRdPerm, &(**mData).fref);
  156.     
  157.     if ( result ) {
  158.         match_bad_file( nshc_parms, nshc_calls, (StringPtr)fss.name );
  159.         return;
  160.         }
  161. }
  162.  
  163. /* ======================================== */
  164.  
  165. void match_read_write( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_hndl mData )
  166. {
  167.     char    c;
  168.     int        close;
  169.     int        i,j;
  170.     int        temp;
  171.     int        result;
  172.     long    bcount;
  173.     char    buf[MATCH_BUF_SIZE+1];
  174.     char    *filename;
  175.     
  176.     result = close = 0;
  177.     
  178.     // =====> copy the data fork
  179.     
  180.     bcount = MATCH_BUF_SIZE;
  181.     result = FSRead( (**mData).fref, &bcount, &buf );
  182.     
  183.     if (( result == noErr ) || ( result == eofErr )) {
  184.     
  185.         if (result == eofErr) {
  186.             close = 1;
  187.             result = 0;
  188.             }
  189.         
  190.         if (bcount) {
  191.             j = (**mData).line_pos;
  192.             for ( i = 0 ; i < bcount ; i++ ) {
  193.                 c = buf[i];
  194.                 if ( c && ( c != '\r' ) && ( j < 255 ) )
  195.                     (**mData).line[++j] = c;
  196.                 else {
  197.                     (**mData).line[0] = j;
  198.                     HLock( mData );
  199.                     if ( !nshc_calls->NSH_match( (**mData).pattern, (**mData).line ) ) {
  200.                         filename = &nshc_parms->arg_buf[nshc_parms->argv[(**mData).arg-1]];
  201.                         nshc_calls->NSH_puts( filename );
  202.                         nshc_calls->NSH_putStr( "\p: " );
  203.                         nshc_calls->NSH_putStr( (**mData).line );
  204.                         nshc_calls->NSH_putchar( '\r' );
  205.                         (**mData).found = 1;
  206.                         }
  207.                     HUnlock( mData );
  208.                     j = 0;
  209.                     }
  210.                 }
  211.             (**mData).line_pos = j;
  212.             }
  213.     
  214.         }
  215.     else
  216.         match_bad_file( nshc_parms, nshc_calls, "\pread data" );
  217.     
  218.     // =====> close the input file
  219.     
  220.     if (close) {
  221.  
  222.         if ( (**mData).fref ) {
  223.             if ( temp = FSClose( (**mData).fref ) )
  224.                 result = temp;
  225.             (**mData).fref = 0;
  226.             }
  227.             
  228.         if (result)
  229.             match_bad_file( nshc_parms, nshc_calls, "\pclose file" );
  230.                 
  231.         }
  232. }
  233.  
  234. /* ======================================== */
  235.  
  236. // console access routines
  237.  
  238. /* ======================================== */
  239.  
  240. void match_console( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls, t_match_hndl mData )
  241. {
  242.     long    bcount;
  243.     Str255    buf;
  244.     char    c;
  245.     int        i;
  246.     int        temp;
  247.     
  248.     bcount = nshc_calls->NSH_getStr( buf );
  249.     
  250.     if (!bcount) return;            // wait for characters
  251.     
  252.     if ( !nshc_calls->NSH_match( (**mData).pattern, buf ) ) {
  253.         nshc_calls->NSH_putStr( buf );    // display the line
  254.         (**mData).found = 1;
  255.         }
  256.     
  257.     if ( bcount == -1 )                // end of input, set-up for exit
  258.         match_good( nshc_parms, mData );
  259. }
  260.  
  261. /* ======================================== */
  262.  
  263. // state machine - core routines
  264.  
  265. /* ======================================== */
  266.  
  267. void match_start( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls  )
  268. {
  269.     int                arg;
  270.     char             *p;
  271.     t_match_hndl    mData;    // handle to hold our data
  272.     
  273.     nshc_parms->action = nsh_continue;
  274.  
  275.     mData = (t_match_hndl )NewHandleClear(sizeof(t_match_data));
  276.     
  277.     if (mData) {
  278.         nshc_parms->data = (Handle)mData;            // save the handle to our data
  279.         (**mData).arg = 1;                            // start at the arg = 1 position
  280.         (**mData).by_file = nshc_parms->argc > 3;    // if we have other args, do file i/o
  281.         (**mData).got_fss = fss_test();                // test if we can use FSSpec calls
  282.  
  283.         arg = nshc_got_option( nshc_parms, 'p' );    // get the position of '-p' arg
  284.         (**mData).p_arg = arg;                    // and save it
  285.         
  286.         if ( arg && ( ++arg < nshc_parms->argc ) ) {
  287.             p = &nshc_parms->arg_buf[nshc_parms->argv[arg]];
  288.             if ( cStrLen( p ) < 253 ) {
  289.                 (**mData).pattern[0] = 1;
  290.                 (**mData).pattern[1] = '*';
  291.                 pStrAppendC( (**mData).pattern, p );
  292.                 pStrAppendC( (**mData).pattern, "*" );
  293.                 }
  294.             else {
  295.                 nshc_calls->NSH_putStr_err( "\pmatch: Pattern is too long.\r" );
  296.                 match_bad( nshc_parms, NSHC_ERR_PARMS );
  297.                 }
  298.             }
  299.         else {
  300.             nshc_calls->NSH_putStr_err( "\pUsage: match -p pattern [files...]\r" );
  301.             match_bad( nshc_parms, NSHC_ERR_PARMS );
  302.             }
  303.         
  304.         }
  305.     else {
  306.         nshc_calls->NSH_putStr_err( "\pmatch: Could not allocate storage.\r" );
  307.         match_bad( nshc_parms, NSHC_ERR_MEMORY );
  308.         }
  309. }
  310.  
  311. /* ======================================== */
  312.  
  313. void match_continue( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  314. {
  315.     t_match_hndl     mData;
  316.  
  317.     if (mData = (t_match_hndl )nshc_parms->data) {
  318.  
  319.         if ( (**mData).by_file ) {
  320.         
  321.             // if we are not in the middle of a file, open one
  322.  
  323.             if ( !(**mData).fref )
  324.                 match_open( nshc_parms, nshc_calls, mData );
  325.  
  326.             // read and write some of the open file
  327.  
  328.             if ( (**mData).fref )
  329.                 match_read_write( nshc_parms, nshc_calls, mData );
  330.  
  331.             // and see if we are done
  332.  
  333.             if ( !(**mData).fref && ( (**mData).arg >= nshc_parms->argc ) )
  334.                 match_good( nshc_parms, mData );
  335.                 
  336.             }
  337.         else
  338.             match_console( nshc_parms, nshc_calls, mData );
  339.  
  340.         }
  341. }
  342.  
  343. /* ======================================== */
  344.  
  345. void match_stop( t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls )
  346. {
  347.     short            fRef;
  348.     t_match_hndl     mData;
  349.     int                temp;
  350.     int                result;
  351.     
  352.     result = 0;
  353.     
  354.     if (mData = (t_match_hndl )nshc_parms->data) {
  355.     
  356.         if ( (**mData).fref ) {
  357.             if ( temp = FSClose( (**mData).fref ) )
  358.                 result = temp;
  359.             (**mData).fref = 0;
  360.             }
  361.             
  362.         DisposeHandle(nshc_parms->data);
  363.         }
  364.         
  365.     if (result)
  366.         match_bad_file( nshc_parms, nshc_calls, "\pclosing files" );
  367.         
  368.     nshc_parms->action = nsh_idle;
  369. }
  370.  
  371. /* ======================================== */
  372.  
  373. void main(t_nshc_parms *nshc_parms, t_nshc_calls *nshc_calls)
  374. {
  375. #ifdef __MWERKS__
  376.     long oldA4  = SetCurrentA4();
  377. #endif
  378.     
  379.     if ( !nshc_bad_version( nshc_parms, nshc_calls, NSHC_VERSION ) ) {
  380.     
  381.         switch (nshc_parms->action) {
  382.             case nsh_start:
  383.                 match_start(nshc_parms, nshc_calls);
  384.                 break;
  385.             case nsh_continue:
  386.                 match_continue(nshc_parms, nshc_calls);
  387.                 break;
  388.             case nsh_stop:
  389.                 match_stop(nshc_parms, nshc_calls);
  390.                 break;
  391.             }
  392.         
  393.         }
  394.  
  395. #ifdef __MWERKS__
  396.     SetA4(oldA4);
  397. #endif
  398. }
  399.  
  400. /* ======================================== */
  401.